/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include <queue>
#include <windows.h>

#include "ui菜单.h"

#include "UI/布局.h"
#include "UI/ui绘制模板.h"
#include "UI/UI.h"

#include <字符串/str_分割.h>
#include "底层绘图/intern/Vulkan/Vulkan框架.h"


static bool g弹出菜单是否打开 = false;
static bool g上层鼠标以移出 = false;


C_菜单* C_菜单::m_当前打开菜单 = 0;


static const vec2	g菜单边界宽度 = { 20, 20 };
static bool			g鼠标进入横向菜单打开纵向菜单 = false;
static int32		g当前焦点部件层 = -1;

static float32 g菜单项圆角 = 4;
static float32 g菜单文件间隔 = 1;
static float32 g菜单顶部偏移 = 10;
static float32 g图标宽度 = 30;

static HANDLE hThread = 0;

static std::queue<C_Widget管理*>	g异步关闭菜单;
static std::mutex					g异步关闭菜单锁; 

struct S_菜单延迟构建缓存 {
	S_菜单创建参数	m_菜单构建参数;
	C_菜单*			m_菜单;
	C_Widget*		m_发起组件;
	vec2			m_添加坐标;
	bool			m_打开;
};
static std::vector<S_菜单延迟构建缓存>		g_菜单延迟添加缓存;





DWORD WINAPI f_弹出窗口延迟关闭(LPVOID pParam) {
	Sleep(600);

	C_Widget* menu = static_cast<C_Widget*>(pParam);
	if (g上层鼠标以移出) {
		C_Widget管理* gm = menu->f_get窗口管理();

		if (g当前焦点部件层 == menu->m_窗口层) {
			f_widget_顶层窗口_pop(gm, 0);
		}
		else {
			f_widget_顶层窗口_pop(gm, menu->m_窗口层 - 1);
		}
		
		g弹出菜单是否打开 = false;
	}
	
	switch (menu->m_Type) {
		case E_WidgetType::t_菜单: {
			CloseHandle(static_cast<C_菜单*>(menu)->m_打开线程);
			static_cast<C_菜单*>(menu)->m_打开线程 = nullptr;
			break;
		}
		case E_WidgetType::t_弹出消息框: {
			CloseHandle(static_cast<C_弹出信息框*>(menu)->m_打开线程);
			static_cast<C_弹出信息框*>(menu)->m_打开线程 = nullptr;
			break;
		}
		default:
			break;
	}

	return 0;
}

auto f_异步添加关闭菜单 = [&](C_Widget管理* gm){
	g异步关闭菜单锁.lock();
	g异步关闭菜单.push(gm);
	g异步关闭菜单锁.unlock();
};




static E_事件是否传递 on_鼠标进入菜单(C_Widget* self, const S_鼠标& 轮值) {
	C_菜单* menu = dynamic_cast<C_菜单*>(self);
	g上层鼠标以移出 = false;

	auto gm = menu->f_get窗口管理();
	
	if (g当前焦点部件层 > menu->m_窗口层) {
		f_widget_顶层窗口_pop(gm, menu->m_窗口层);
	}

	if (menu->m_排列方向 == E_方向::e_纵向) {
		g鼠标进入横向菜单打开纵向菜单 = true;
	}

	return E_事件是否传递::e_事件传递_继续;
}

static E_事件是否传递 on_鼠标移出菜单(C_Widget* self, const S_鼠标& 轮值) {
	C_菜单* menu = dynamic_cast<C_菜单*>(self);
	
	if (menu->m_排列方向 == E_方向::e_纵向) {
		g鼠标进入横向菜单打开纵向菜单 = false;
	}

	g上层鼠标以移出 = true;

	if (menu->m_鼠标离开关闭菜单) {
		//创建线程
		menu->m_打开线程 = CreateThread(NULL, 0, f_弹出窗口延迟关闭, menu, 0, NULL);
	}
	
	g当前焦点部件层 = menu->m_窗口层;
	return E_事件是否传递::e_事件传递_继续;
}



static void f_横向菜单布局(C_Widget* self, C_Widget** w, uint32 num) {
	C_菜单& menu = *static_cast<C_菜单*>(self);

	float32 dpi = self->m_UIctx->m_DPI;

	vec2 pos = { float32(self->m_间隔宽度 + 10) * dpi, 0 };
	vec2 h{(self->m_Size.y - (g菜单项圆角 * 2 * 0.8f * dpi)) };
	h.y = self->m_Size.y - self->m_间隔宽度 * 2 * dpi;

	for (uint32 i = 0; i < num; ++i) {
		float32 w1 = f_vg_getStringSize(*menu.m_字符, w[i]->m_WName, self->m_Size.y, S_UI主题::ui_文字间隔 * dpi);
		h.x = max(h.x, w1);
	}
	h.x += 30 * dpi;


	for (uint32 i = 0; i < num; ++i) {
		w[i]->f_setPos(pos);
		w[i]->f_setSize(h);

		pos.x += w[i]->m_Size.x + dpi*3;
	}
}

static void f_横向菜单绘制(C_Widget* self, S_2D画布* 画布) {
	C_菜单& menu = *static_cast<C_菜单*>(self);
	menu.m_背景 = f_vg_genConvex((*self), *画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal);
	menu.m_字符 = f_vg_genString((*self), *画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal, u"雅黑");
}

static void f_横向菜单变换(C_Widget* self) {
	auto* rf = f_vk_get绘图框架((*self));

	C_菜单& menu = *static_cast<C_菜单*>(self);
	auto we = menu.f_get更新组件();
	float32 dpi = self->m_UIctx->m_DPI;
	
	

	std::vector<S_2DConvexRect> rect(we.m_Num + 1);
	std::vector<S_GPU内存块*>	形状(we.m_Num + 1);
	std::vector<S_RGBA8UI>		颜色(we.m_Num + 1);
	std::vector<vec2>			位置(we.m_Num + 1);


	std::vector<std::u16string> 标题字符(we.m_Num);
	std::vector<S_Rect2Df>		标题区域(we.m_Num);
	std::vector<S_RGBA8UI>		标题颜色(we.m_Num);

	位置[0] = {};
	形状[0] = &S_2D画布::g预设_下圆角矩形;
	颜色[0] = S_UI主题::uic_菜单条背景;

	rect[0].offset = {};
	rect[0].size = self->m_Size;
	rect[0].radius = { S_UI主题::ui_面板圆角半径, S_UI主题::ui_面板圆角半径 };
	rect[0].AA_type = { 1, 0 };

	auto* l = &位置[1];
	auto* s = &形状[1];
	auto* r = &rect[1];
	auto* c = &颜色[1];


	for (uint32 i = 0; i < we.m_Num; ++i) {
		s[i] = &((*self).m_UIctx->m_Ctx.m_几何图形->m_平面圆角矩形);

		l[i] = we.m_W[i]->m_Pos;

		r[i].offset = {};
		r[i].size = we.m_W[i]->m_Size;
		r[i].radius = { S_UI主题::ui_面板圆角半径, S_UI主题::ui_面板圆角半径 };
		r[i].AA_type = { 1, 0 };
		c[i] = we.m_W[i]->m_颜色A + 5;

		//描边颜色[i+1] = S_2D颜色包();

		标题字符[i] = dynamic_cast<C_菜单项*>(we.m_W[i])->m_主语言_标题;
		标题区域[i] = { we.m_W[i]->m_Pos, r[i].size };
		标题颜色[i] = S_UI主题::uic_文字颜色;
	}
	
	f_vg_tranform(*menu.m_背景, 位置.size(), 位置.data());
	f_vg_drawConvex(*menu.m_背景, we.m_Num + 1, 形状.data(), rect.data());
	f_vg_color(*menu.m_背景, we.m_Num + 1, 颜色.data());


	S_行字符串绘制属性 字符串绘制属性;
	字符串绘制属性.m_间距 = S_UI主题::ui_文字间隔 * dpi;
	字符串绘制属性.m_方向 = E_方向::e_横向;
	f_vg_drawString(*menu.m_字符, 标题字符, 标题区域, 标题颜色, E_对齐方式::e_据中对齐, 字符串绘制属性);
}









static E_事件是否传递 on_纵向菜单_按键按下(C_Widget* self, const S_键盘& ks) {
	C_菜单& menu = *dynamic_cast<C_菜单*>((C_Widget*)self);
	//std::cout<<"on_纵向菜单_按键按下\n";
	if (menu.m_当前焦点ID < menu.m_子组件.size()) {
		C_菜单项* selfItem = dynamic_cast<C_菜单项*>(menu.m_子组件[menu.m_当前焦点ID]);
		if (f_KS(C_Widget::g_键盘, S_InputKey::e_KEY_回车) == DEF_按键状态_按下) {
			g弹出菜单是否打开 = false;
			f_widget_top_close(self->f_get窗口管理());
		}
		else if (f_KS(C_Widget::g_键盘, S_InputKey::e_KEY_方向_下) == DEF_按键状态_按下) {
			++menu.m_当前焦点ID;
			if(menu.m_当前焦点ID >= menu.m_子组件.size()) menu.m_当前焦点ID = menu.m_子组件.size() - 1;
		}
		else if (f_KS(C_Widget::g_键盘, S_InputKey::e_KEY_方向_上) == DEF_按键状态_按下) {
			--menu.m_当前焦点ID;
			if(menu.m_当前焦点ID < 0) menu.m_当前焦点ID = 0;
		}
		else {
			return E_事件是否传递::e_事件传递_继续;
		}

		self->m_更新绘制属性 = true;
	}
	//f_文本编辑框_控制键输入(editBox, ks, 0);
	return E_事件是否传递::e_事件传递_终止;
}

static void f_纵向菜单布局(C_Widget* self, C_Widget** w, uint32 num) {
	C_菜单& menu = *dynamic_cast<C_菜单*>((C_Widget*)self);
	auto* rf = f_vk_get绘图框架((*self));

	auto& font = rf->m_字体[u"雅黑"];
	float32 dpi = self->m_UIctx->m_DPI;

	float32 maxWidth = 30 * dpi;
	float32 maxHeigth = g菜单顶部偏移;
	for (int32 i = 0; i < num; ++i) {
		C_菜单项* item = dynamic_cast<C_菜单项*>(w[i]);
		if (item) {
			if (item->m_主语言_标题.empty()) {
				item->f_setH(4 * dpi);
			}
			else {
				item->f_setH(24 * dpi);
			}
			
			float32 w1 = f_vg_getStringSize(font, item->f_getTitle(), item->m_Size.y, S_UI主题::ui_文字间隔*dpi);
			float32 w2 = f_vg_getStringSize(font, item->m_快捷键, item->m_Size.y, S_UI主题::ui_文字间隔*dpi);

			maxWidth = DEF_Max(maxWidth, DEF_Max(w1, w2));
		}
		maxHeigth + 20;
	}
	maxWidth += g图标宽度 * 2 + dpi*10;


	vec2 size;
	vec2 pos = {menu.m_间隔宽度, g菜单顶部偏移};
	for (uint32 i = 0; i < num; ++i) {
		w[i]->f_setPos(pos);
		w[i]->f_setW(maxWidth);

		pos.y += w[i]->m_Size.y;
	}
	size.x = maxWidth + menu.m_间隔宽度 * 2;
	size.y = pos.y + g菜单顶部偏移;
	
	self->f_setSize(size);
}

static void f_纵向菜单绘制(C_Widget* self, S_2D画布* 画布) {
	C_菜单& menu = *dynamic_cast<C_菜单*>(self);

	menu.m_背景 = f_vg_genConvex((*self), *画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal);
	menu.m_描边 = f_vg_genConvex((*self), *画布, E_填充模式::e_填充线, E_图层混合模式::e_Normal);
	
	menu.m_字符 = f_vg_genString((*self), *画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal, u"雅黑");
	menu.m_分隔线 = f_vg_genLine((*self), *画布, E_图层混合模式::e_Normal, E_线类型::e_线段);
}

static void f_纵向菜单变换(C_Widget* self) {
	C_菜单& menu = *dynamic_cast<C_菜单*>(self);
	float32 dpi = self->m_UIctx->m_DPI;

	auto e = self->f_get更新组件();

	std::vector<S_2DConvexRect>	区域(1);
	std::vector<S_GPU内存块*>	形状(1);
	std::vector<S_2D颜色包>		颜色(1);
	std::vector<vec2>			位置(1);

	std::vector<S_2D颜色包>		描边颜色(1);

	区域.reserve(e.m_Num);
	形状.reserve(e.m_Num);
	颜色.reserve(e.m_Num);
	位置.reserve(e.m_Num);
	//描边颜色.reserve(e.m_Num);

	形状[0] = &(self->m_UIctx->m_Ctx.m_几何图形->m_平面圆角矩形);
	区域[0].size = { self->m_Size.x - menu.m_间隔宽度 * 2, self->m_Size.y };
	区域[0].radius = {S_UI主题::ui_面板圆角半径, S_UI主题::ui_面板圆角半径};
	区域[0].AA_type = { 1, 0 };
	位置[0] = { float32(menu.m_间隔宽度), 0};
	颜色[0] = menu.m_ColorA;
	
	描边颜色[0] = S_2D颜色包({0,200,220,60}, 0, 0, DEF_2DCompositionType_Background);


	std::vector<vec2> 分割线;
	分割线.reserve(20);

	std::vector<std::u16string> 字符文本;
	std::vector<S_Rect2Df>		字符区域;
	std::vector<S_RGBA8UI>		字符颜色;
	std::vector<E_对齐方式>		字符对齐;

	std::vector<S_GPU内存块*>	线形状;
	std::vector<vec2>			线位置;
	std::vector<vec2>			线大小;
	std::vector<S_RGBA8UI>		线颜色;
	
	字符文本.reserve(e.m_Num);
	字符区域.reserve(e.m_Num);
	字符颜色.reserve(e.m_Num);
	字符对齐.reserve(e.m_Num);

	
	for (uint32 i = 0; i < e.m_Num; ++i) {
		S_2DConvexRect rect{};
		rect.size = e.m_W[i]->m_Size - 6*dpi;
		rect.radius = {S_UI主题::ui_面板圆角半径, S_UI主题::ui_面板圆角半径};
		rect.AA_type = {1, 0};

		vec2 pos = e.m_W[i]->m_Pos + 3*dpi;
		区域.push_back(rect);
		位置.push_back(pos);
		形状.push_back(&(self->m_UIctx->m_Ctx.m_几何图形->m_平面圆角矩形));

		if (menu.m_当前焦点ID >= 0) {
			if (menu.m_当前焦点ID == i) {
				颜色.push_back(S_2D颜色包(S_UI主题::uic_焦点色));
			}
			else {
				颜色.push_back(S_2D颜色包(S_RGBA8UI{}));
			}
		}
		else {
			颜色.push_back(S_2D颜色包(e.m_W[i]->m_颜色A));
		}
		
		

		//std::u16string_view t2(u"mbt");

		//描边颜色.emplace_back(S_2D颜色包());
		std::u16string t;
		if (e.m_W[i]->m_Type == E_WidgetType::t_菜单项) {
			t = ((C_菜单项*)e.m_W[i])->m_主语言_标题;

			if (t.empty()) {

				线形状.push_back(&(self->m_UIctx->m_Ctx.m_几何图形->m_平面横向直线));
				线位置.push_back(e.m_W[i]->m_Pos + vec2{4,2}*dpi);
				线大小.push_back(e.m_W[i]->m_Size - vec2{8,2}*dpi);

				线颜色.push_back(S_UI主题::uic_菜单分割项);
			}
		}

		pos.x += 10*dpi;
		rect.size.x -= 20*dpi;

		字符文本.push_back(t);
		字符区域.push_back({pos, rect.size});
		字符颜色.push_back(S_UI主题::uic_文字颜色);
		字符对齐.emplace_back(E_对齐方式::e_左对齐);

		字符文本.push_back(((C_菜单项*)e.m_W[i])->m_快捷键);
		字符区域.push_back({pos, rect.size});
		字符颜色.push_back(S_UI主题::uic_文字颜色 - 40);
		字符对齐.emplace_back(E_对齐方式::e_右对齐);
	}

	f_vg_drawConvex(*menu.m_背景, 区域.size(), 形状.data(), 区域.data());
	f_vg_tranform(*menu.m_背景, 位置.size(), 位置.data());
	f_vg_color(*menu.m_背景, 颜色.size(), 颜色.data());

	f_vg_drawConvex(*menu.m_描边, 1, 形状.data(), 区域.data(), 0.5);
	f_vg_tranform(*menu.m_描边, 1, 位置.data());
	f_vg_color(*menu.m_描边, 1, 描边颜色.data());


	S_行字符串绘制属性 字符串绘制属性;
	字符串绘制属性.m_间距 = S_UI主题::ui_文字间隔 * dpi;
	字符串绘制属性.m_方向 = E_方向::e_横向;
	f_vg_drawString(*menu.m_字符, 字符文本, 字符区域, 字符颜色, 字符对齐, 字符串绘制属性);

	f_vg_setLine(*menu.m_分隔线, 线形状.size(), 线形状.data(), 2);
	f_vg_tranform(*menu.m_分隔线, 线位置.size(), 线位置.data(), 线大小.data());
	f_vg_color(*menu.m_分隔线, 线颜色.size(), 线颜色.data());
}



C_菜单::C_菜单(E_方向 dir, S_UI渲染环境& ctx) : C_Widget(&ctx), m_排列方向(dir) {
	m_Type = E_WidgetType::t_菜单;
	m_TypeName = "C_菜单";

	mui_发起组件 = nullptr;
	m_当前焦点ID = -1;
	m_打开线程 = nullptr;
	
	f_setMinSize({ 40 * ctx.m_DPI, 24 * ctx.m_DPI });
	f_widget_添加绘制画布(this);

	if (dir == E_方向::e_横向) {
		m_间隔宽度 = 1;

		mf_布局 = f_横向菜单布局;
		mf_绘制 = f_横向菜单绘制;
		mf_变换 = f_横向菜单变换;
	}
	else if (dir == E_方向::e_纵向) {
		m_间隔宽度 = g菜单边界宽度.x;

		mf_布局 = f_纵向菜单布局;
		mf_绘制 = f_纵向菜单绘制;
		mf_变换 = f_纵向菜单变换;

		mf_键盘按键敲击	= on_纵向菜单_按键按下;

		m_ColorA = S_2D颜色包(S_UI主题::uic_菜单背景, 128, 30, 0);
	}

	mf_鼠标进入 = on_鼠标进入菜单;
	mf_鼠标离开 = on_鼠标移出菜单;
	mui_搜索框 = nullptr;

	m_鼠标离开关闭菜单 = true;

}

C_菜单::~C_菜单() {
	if (m_打开线程) {
		WaitForSingleObject(m_打开线程, INFINITE);
	}
}

void C_菜单::f_打开(const vec2& pos, const bool 记忆) {
	vec2 偏移 = pos;
	//偏移.x -= g菜单边界宽度.x * m_UIctx->m_DPI;
	偏移.x -= m_间隔宽度;


	if (mui_搜索框) {
		uint32 num = mui_根菜单项.size();

		m_子组件.resize(num + 1);
		for (uint32 i = 0; i < num; ++i) {
			m_子组件[i + 1] = mui_根菜单项[i];
		}

		f_widget_set当前激活编辑框(mui_搜索框);
	}

	f_setPos(偏移);

	m_GlobalLoc			= 偏移;
	m_更新绘制属性		= true;
	g弹出菜单是否打开	= true;
	g当前焦点部件层		= m_窗口层;
}

void C_菜单::f_关闭() {
	
}

C_菜单项* C_菜单::f_创建项(const std::u16string txt, std::u16string ico, std::u16string key) {
	C_菜单项* item = new C_菜单项(*m_UIctx, txt, ico, 24 * m_UIctx->m_DPI);

	item->m_快捷键 = key;
	item->m_实例ID = this->f_get子部件数量();
	f_添加子组件(item);
	
	if (mui_搜索框) {
		mui_根菜单项.push_back(item);
	}
	return item;
}

void C_菜单::f_添加项(C_菜单项* item) {

}

void C_菜单::f_移除项(C_菜单项 * itme) {
	
}

void C_菜单::f_设置项冻结(uint32 id, bool y) {
	
}

void C_菜单::f_切换搜索菜单项(std::vector<C_菜单项>& items) {
	
}





static E_事件是否传递 on_菜单项鼠标进入事件(C_Widget* self, const S_鼠标& 轮值) {
	C_菜单项* item = dynamic_cast<C_菜单项*>(self);
	
	if (item) {
		C_菜单* menu = dynamic_cast<C_菜单*>(item->m_父部件);
		if (!menu) return E_事件是否传递::e_事件传递_继续;
		
		if (menu->m_当前焦点ID < 0) {
			item->m_颜色A = S_UI主题::uic_焦点色;
		}
		
		//menu->m_更新绘制属性 = true;
		f_widget_更新绘制(menu);
		
		if (menu->m_排列方向 == E_方向::e_纵向) {
			//=================== 纵向菜单焦点变换属性 ===================
			
		}
		else {
			//===================== 在横向菜单中自动打开纵向菜单 ==================
			if (menu->m_窗口层 == 0 && g弹出菜单是否打开) {
				f_widget_top_close(item->f_get窗口管理());

				if (item->ui_子菜单) {
					f_widget_top_push(item->ui_子菜单, menu->m_窗口层);

					item->ui_子菜单->mui_发起组件 = menu->mui_发起组件;
					item->ui_子菜单->f_打开({ item->m_裁剪大小.x, item->m_裁剪大小.w });
				}
			}
		}
	}
	//std::cout << "**********************菜单项进入空事件:" << ((C_Widget*)w)->m_Name << std::endl;
	return E_事件是否传递::e_事件传递_继续;
}
static E_事件是否传递 on_菜单项鼠标移除事件(C_Widget* self, const S_鼠标& 轮值) {
	C_菜单项* item = dynamic_cast<C_菜单项*>(self);

	if (item) {
		C_菜单* menu = dynamic_cast<C_菜单*>(item->m_父部件);
		if (!menu) return E_事件是否传递::e_事件传递_继续;

		if (menu->m_当前焦点ID < 0) {
			item->m_颜色A = {};
		}

		//menu->m_更新绘制属性 = true;
		f_widget_更新绘制(menu);
	}
	
	return E_事件是否传递::e_事件传递_继续;
}




static E_事件是否传递 on_菜单项点击事件(C_Widget* self, const E_鼠标按钮& 按钮) {
	C_菜单项* selfItem = dynamic_cast<C_菜单项*>(self);
	C_菜单* menu = dynamic_cast<C_菜单*>(selfItem->m_父部件);

	
	//打开子菜单
	if (selfItem->ui_子菜单) {
		
		if (menu->m_排列方向 == E_方向::e_纵向) {
			//f_widget_顶层窗口_pop(self->f_get窗口管理(), menu->m_窗口层);

			vec2 pos = { selfItem->m_裁剪大小.z, selfItem->m_裁剪大小.y - g菜单顶部偏移 };
			pos = f_widget_弹出窗口坐标矫正(selfItem->ui_子菜单, pos);

			selfItem->ui_子菜单->f_打开(pos);
		}
		else {
			selfItem->ui_子菜单->f_打开({ selfItem->m_裁剪大小.x, selfItem->m_裁剪大小.w });
		}
		selfItem->ui_子菜单->mui_发起组件 = menu->mui_发起组件;

		//f_widget_set绘制根区域组件(selfItem->ui_子菜单, selfItem->ui_子菜单);
		f_widget_加入顶层绘图(selfItem->ui_子菜单);

		f_widget_top_push(self->f_get窗口管理(), selfItem->ui_子菜单);
	}
	else if(selfItem->mf_菜单事件) {
		g弹出菜单是否打开 = false;
		f_widget_顶层窗口_pop(self->f_get窗口管理(), 0);

		if (selfItem->mf_菜单事件) {
			if (selfItem->mf_菜单事件(selfItem, selfItem->f_getTitle(), selfItem->m_实例ID)) {
				return E_事件是否传递::e_事件传递_终止;
			}
		}
	}
	
	return E_事件是否传递::e_事件传递_终止;
}


C_菜单项::C_菜单项(S_UI渲染环境& ctx, const std::u16string txt, const std::u16string& ico, float32 菜单厚度) : C_Widget(&ctx), m_主语言_标题(txt) {
	m_TypeName = "C_菜单项";
	m_Type = E_WidgetType::t_菜单项;
	ui_子菜单 = nullptr;
	m_颜色A = {0,0,0,0};
	m_ICO = ico;

	if (m_主语言_标题.empty()) {
		f_setMinSize({ m_UIctx->m_DPI*26.0f, 6 });
	}
	else {
		f_setMinSize({ m_UIctx->m_DPI*26.0f, 24 * m_UIctx->m_DPI });
	}
	

	mf_鼠标进入 = on_菜单项鼠标进入事件;
	mf_鼠标离开 = on_菜单项鼠标移除事件;

	mf_鼠标点击 = on_菜单项点击事件;
	mf_菜单事件 = nullptr;

}




C_菜单* C_菜单项::f_添加子菜单(uint32 layer, S_UI渲染环境& ctx) {
	ui_子菜单 = new C_菜单(E_方向::e_纵向, ctx);
	ui_子菜单->m_窗口层 = layer;

	return ui_子菜单;
}


void C_菜单项::f_关闭菜单链(C_Widget* w) {
	if (w) {
		
	}
}






struct S_菜单排序项 {
	C_菜单项* 项;
	float32 权重;
};

static bool f_项排序对比(const S_菜单排序项& ia, const S_菜单排序项& ib) {
	return (ia.权重 > ib.权重);
}

void on_菜单搜索项完成(S_Props& prop) {
	auto s = f_prop_LineStr(prop);
}

static void on_菜单搜索项(C_Widget* self, const std::u16string& text, E_字符输入类型 输入类型) {
	C_菜单& menu = *dynamic_cast<C_菜单*>(self->m_父部件);

	if (text.size()) {
		auto w = menu.mui_搜索菜单项.data();
		uint32 num = menu.mui_搜索菜单项.size();

		std::vector<S_菜单排序项> 待排序项;
		for (uint32 i = 0; i < num; ++i) {
			float32 权重1 = f_str_对比所占权重(text, w[i]->m_主语言_标题, false);
			float32 权重2 = f_str_对比所占权重(text, f_str_转小写(w[i]->m_英语_标题), true);

			if (权重1 > 0 || 权重2 > 0) {
				if (权重1 > 权重2) {
					待排序项.push_back({ w[i], 权重1 });
				}
				else {
					待排序项.push_back({ w[i], 权重2 });
				}
			}
		}

		std::sort(待排序项.begin(), 待排序项.end(), f_项排序对比);
		num = 待排序项.size();

		uint32 已有数量 = menu.m_子组件.size();

		menu.m_子组件.resize(num + 1);
		for (uint32 i = 0; i < num; ++i) {
			f_widget_set子组件(&menu, 待排序项[i].项, i + 1);
		}
	}
	else {
		uint32 num = menu.mui_根菜单项.size();
		menu.m_子组件.resize(num + 1);
		for (uint32 i = 0; i < num; ++i) {
			menu.m_子组件[i + 1] = menu.mui_根菜单项[i];
		}
	}
	
	//menu.m_更新绘制属性 = true;
}

C_菜单项* f_ui_创建菜单项(S_UI渲染环境& ctx, S_菜单项创建参数& pip, fp_on_菜单项点击 菜单项点击) {
	C_菜单项* item = new C_菜单项(ctx, pip.name, pip.ico, 30 * ctx.m_DPI);

	item->mf_菜单事件 = 菜单项点击;
	item->m_ICO = pip.ico;

	return item;
}

void f_ui_添加菜单项(C_Widget* self, S_菜单创建参数 pip, S_UI渲染环境& ctx, uint16 layers, float32 width ) {
	C_菜单* menu = dynamic_cast<C_菜单*>(self);
	
	if (menu) {
		menu->m_窗口层 = layers;
		uint32 ID = 0;
		for (auto& item : pip.item) {
			C_菜单项* sonItem = menu->f_创建项(item.name, item.ico, item.快捷键);

			sonItem->mf_菜单事件 = pip.mf_菜单项点击;
			sonItem->m_实例ID = ID;
			sonItem->m_Size.x = width;
			++ID;

			if (item.子菜单参数) {
				C_菜单* sonMenu = sonItem->f_添加子菜单(layers + 1, ctx);
				S_菜单创建参数& 子项参数 = *((S_菜单创建参数*)item.子菜单参数);
				f_ui_添加菜单项(sonMenu, 子项参数, ctx, layers + 1, width);
			}
		}
	}
}

void f_ui_添加菜单项(C_Widget* self, S_菜单创建参数 pip, uint16 layers, float32 width) {
	f_ui_添加菜单项(self, pip, *self->m_UIctx, layers, width);
}

C_Widget* f_ui_创建菜单(S_UI渲染环境& ctx, E_方向 dir, const S_菜单创建参数& ini, bool 是否创建搜索) {
	auto ui菜单 = new C_菜单(dir, ctx);
	f_ui_添加菜单项(ui菜单, ini, ctx, 1);

	if (是否创建搜索) {
		ui菜单->m_搜索文本 = f_alloc_LineStrProp(nullptr, u"");
		ui菜单->m_搜索文本.m_UI->m_Update = on_菜单搜索项完成;

		ui菜单->mui_搜索框 = new C_行编辑框(ctx);
		
		ui菜单->mui_搜索框->f_bind属性(ui菜单->m_搜索文本);
		ui菜单->mui_搜索框->m_TypeName;
		ui菜单->mui_搜索框->m_ICO = u"放大镜";
		ui菜单->mui_搜索框->mf_文本输入 = on_菜单搜索项;
		ui菜单->mui_搜索框->f_setMinSize({30,30});

		ui菜单->mui_根菜单项 = ui菜单->m_子组件;
		ui菜单->f_添加子组件(ui菜单->mui_搜索框, 0);
	}

	return ui菜单;
}

C_Widget* f_ui_创建菜单(S_UI渲染环境& ctx, E_方向 dir) {
	auto ui菜单 = new C_菜单(dir, ctx);
	return ui菜单;
}

void f_ui_销毁菜单(C_Widget* self) {
	delete self;
}

void f_ui_添加菜单搜素项(C_Widget* self, S_菜单创建参数& ini) {
	C_菜单& menu = *static_cast<C_菜单*>(self);

	for (auto& e : ini.item) {
		C_菜单项* item = f_ui_创建菜单项(*self->m_UIctx, e, ini.mf_菜单项点击);

		menu.mui_搜索菜单项.push_back(item);
	}
}

void f_ui_清除菜单搜素项(C_Widget* self) {
	C_菜单& menu = *static_cast<C_菜单*>(self);
	menu.mui_搜索菜单项.clear();
}



void f_ui_填充菜单项(C_Widget* self, const S_菜单创建参数& item, uint16 layers) {
	f_widget_remove所有子部件(self);
	f_ui_添加菜单项(self, item, *self->m_UIctx, layers);
}

void f_ui_添加子菜单项(C_Widget* self, const S_菜单创建参数& item, uint16 layers) {

}



void f_ui_弹出子菜单(C_Widget* 菜单项组件, C_Widget* 子菜单) {
	C_菜单项* 菜单项 = dynamic_cast<C_菜单项*>(菜单项组件);
	C_菜单* 子菜单组件 = dynamic_cast<C_菜单*>(子菜单);

	C_菜单* menu = dynamic_cast<C_菜单*>(菜单项->m_父部件);

	子菜单组件->mui_发起组件 = menu->mui_发起组件;


	f_widget_top_push(子菜单, 子菜单组件->m_窗口层 - 1);

	vec2 pos = { 菜单项组件->m_裁剪大小.z, 菜单项组件->m_裁剪大小.y - g菜单顶部偏移 };
	子菜单组件->f_打开(pos);
}



vec2 f_菜单子项坐标矫正(C_菜单项* 项) {
	auto e = 项->ui_子菜单->f_get更新组件();
	项->ui_子菜单->mf_布局(项->ui_子菜单, e.m_W, e.m_Num);

	vec2 当前菜单大小 = 项->ui_子菜单->m_Size;
	vec4 窗口大小 = f_widget_get当前窗口矩形();
	vec2 pos = { 项->m_裁剪大小.z, 项->m_裁剪大小.y - g菜单顶部偏移 };
	
	if (pos.x + 当前菜单大小.x >= 窗口大小.z) {
		pos.x = (项->m_裁剪大小.x - 当前菜单大小.x + g菜单边界宽度.x*2);
	} 

	if (pos.y + 当前菜单大小.y >= 窗口大小.w) {
		pos.y = (窗口大小.w - 当前菜单大小.y + g菜单边界宽度.x*2);
	}

	return pos;
}

vec2 f_菜单坐标矫正(C_菜单* 菜单, vec2 pos) {
	auto e = 菜单->f_get更新组件();
	菜单->mf_布局(菜单, e.m_W, e.m_Num);

	//vec4 窗口大小 = f_widget_get当前窗口矩形();
	//菜单->m_UIctx->m_GM->视口.width;

	if (pos.x + 菜单->m_Size.x - 菜单->m_间隔宽度 >= 菜单->m_UIctx->m_GM->视口.width) {
		pos.x = 菜单->m_UIctx->m_GM->视口.width - 菜单->m_Size.x + 菜单->m_间隔宽度*2;
	}

	if (pos.y + 菜单->m_Size.y - 菜单->m_间隔宽度 >= 菜单->m_UIctx->m_GM->视口.height) {
		pos.y = 菜单->m_UIctx->m_GM->视口.height - 菜单->m_Size.y + 菜单->m_间隔宽度 * 2;
	}

	return pos;
}





void f_ui_清除菜单项(C_Widget* self) {
	C_菜单& menu = *dynamic_cast<C_菜单*>(self);

	f_widget_remove所有子部件(self);
}

void f_ui_搜索菜单项(C_Widget* self) {
	C_菜单& menu = *dynamic_cast<C_菜单*>(self);

}


C_Widget* f_ui_从菜单项取发起组件(C_Widget* self) {
	C_菜单项* selfItem = dynamic_cast<C_菜单项*>(self);
	C_菜单* menu = dynamic_cast<C_菜单*>(selfItem->m_父部件);

	return menu->mui_发起组件;
}

C_Widget* f_ui_get子菜单项(C_Widget* self, std::vector<std::u16string> name, bool 创建项, uint32 层) {
	C_菜单* menu = dynamic_cast<C_菜单*>(self);
	C_Widget* 目标菜单 = nullptr;

	uint32 层数量 = name.size();
	if (层数量) {
		uint32 i = 0;


		auto t = name.front();

		for (auto& e : menu->m_子组件) {
			C_菜单项* 菜单项 = dynamic_cast<C_菜单项*>(e);
			if(!菜单项) continue;

			if (菜单项->m_主语言_标题 == t) {
				
				if (菜单项->ui_子菜单) {
					name.erase(name.begin());

					目标菜单 = f_ui_get子菜单项(菜单项->ui_子菜单, name, 创建项, 层 + 1);
					if (!目标菜单) {
						目标菜单 = 菜单项;
					}
				}
				else {
					目标菜单 = 菜单项;
				}
				
				break;
			}
		}
	}
	
	if (!目标菜单 && 层数量) {

		if (创建项) {
			S_菜单创建参数 创建参数;
			uint32 i = 0;

			std::vector<S_菜单创建参数> 子项参数(name.size());
			for (auto& n : name) {
				S_菜单项创建参数 item;
				item.name = n;
				item.ico = u"";
				item.子菜单参数 = nullptr;

				子项参数[i].item.push_back(item);
				子项参数[i].mf_菜单项点击 = nullptr;

				if (i) {
					子项参数[i - 1].item.front().子菜单参数 = &子项参数[i];
				}
				++i;
			}

			f_ui_添加菜单项(self, 子项参数.front(), *(self->m_UIctx), 层 + 1);
		}
		
		目标菜单 = f_ui_get子菜单项(self, name, false, 层 + 1);
	}
	
	return 目标菜单;
}

void f_ui_菜单项绑定事件(C_Widget* self, fp_on_菜单项点击 fn) {
	C_菜单项* 菜单项 = dynamic_cast<C_菜单项*>(self);

	菜单项->mf_菜单事件 = fn;
}

void f_ui_菜单关闭方式(C_Widget* self, E_菜单关闭方式 方式) {
	C_菜单* menu = dynamic_cast<C_菜单*>(self);

	menu->m_鼠标离开关闭菜单 = false;
}

void f_ui_置菜单项焦点(C_Widget* self, int32 id) {
	C_菜单* menu = dynamic_cast<C_菜单*>(self);
	menu->m_当前焦点ID = id;

	int32 i = 0;
	for (auto& e : menu->m_子组件) {
		if (i == id) {
			e->m_颜色A = S_UI主题::uic_焦点色;
		}
		else {
			e->m_颜色A = {};
		}
		++i;
	}
}

int32 f_ui_执行菜单项事件(C_Widget* self) {
	
	assert(self->m_Type == E_WidgetType::t_菜单);
	C_菜单* 强制类型 = (C_菜单*)(self);
	C_菜单* dynamic_cast_menu = dynamic_cast<C_菜单*>(self);
	C_菜单* menu = static_cast<C_菜单*>(self);
	//std::cout<<强制类型<<dynamic_cast_menu<<menu;
	if(!g弹出菜单是否打开 || menu->m_当前焦点ID < 0) return -1;
	
	if (menu->m_当前焦点ID >= 0) {
		C_菜单项* item = static_cast<C_菜单项*>(menu->m_子组件[menu->m_当前焦点ID]);
		item->mf_鼠标点击(item, {});
	}

	return menu->m_当前焦点ID;
}

void f_ui_打开动态菜单(C_Widget* self, vec2 pos, C_Widget* 发起组件, const S_菜单创建参数& 创建参数, bool 打开, bool 延迟构建) {
	C_菜单& box = *dynamic_cast<C_菜单*>(self);

	if (延迟构建) {
		S_菜单延迟构建缓存 构建缓存;
		构建缓存.m_菜单构建参数 = 创建参数;
		构建缓存.m_发起组件 = 发起组件;
		构建缓存.m_添加坐标 = pos;
		构建缓存.m_菜单 = dynamic_cast<C_菜单*>(self);
		构建缓存.m_打开 = 打开;

		g_菜单延迟添加缓存.emplace_back(构建缓存);

		f_widget_remove子部件(self, self->m_子组件, false);
	}
	else {
		f_ui_填充菜单项(self, 创建参数);
		f_ui_打开弹出窗口(self, pos, 发起组件);
	}
}

void f_菜单_构建动态菜单() {
	for (auto& e : g_菜单延迟添加缓存) {
		f_ui_填充菜单项(e.m_菜单, e.m_菜单构建参数);

		int32 i = 0;
		for (auto& item : e.m_菜单->m_子组件) {
			if (i == e.m_菜单->m_当前焦点ID) {
				item->m_颜色A = S_UI主题::uic_焦点色;
			}
			else {
				item->m_颜色A = {};
			}
			++i;
		}

		if (e.m_打开) {
			f_ui_打开弹出窗口(e.m_菜单, e.m_添加坐标, e.m_发起组件);
		}
	}
	g_菜单延迟添加缓存.clear();
}

void f_菜单_关闭(C_菜单* menu) {
	auto gm = menu->f_get窗口管理();
	f_widget_顶层窗口_pop(gm, menu->m_窗口层 - 1);

	menu->m_窗口层 = 0;
	menu->m_当前焦点ID = -1;
}






static void on_弹出信息框布局(C_Widget* self, C_Widget** w, uint32 num) {
	C_弹出信息框& box = *dynamic_cast<C_弹出信息框*>(self);
	box.f_setSize({512,720});
}

static void on_弹出信息框绘制(C_Widget* self, S_2D画布* 画布) {
	auto 背景 = f_vg_genConvex((*self), *画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal);
	auto 字符 = f_vg_genString((*self), *画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal, S_UI主题::ui_默认字体);
}

static E_事件是否传递 on_鼠标进入_弹出信息框(C_Widget* self, const S_鼠标& 轮值) {
	C_弹出信息框* menu = dynamic_cast<C_弹出信息框*>(self);
	//f_widget_顶层窗口_pop(self->f_get窗口管理(), menu->m_窗口层);
	g上层鼠标以移出 = false;
	return E_事件是否传递::e_事件传递_继续;
}

static E_事件是否传递 on_鼠标移出_弹出信息框(C_Widget* self, const S_鼠标& 轮值) {
	C_弹出信息框* menu = dynamic_cast<C_弹出信息框*>(self);

	g上层鼠标以移出 = true;
	//创建线程
	hThread = CreateThread(NULL, 0, f_弹出窗口延迟关闭, menu, 0, NULL);

	return E_事件是否传递::e_事件传递_继续;
}


C_弹出信息框::C_弹出信息框(S_UI渲染环境& ctx) : C_Widget(&ctx) {
	m_Type = E_WidgetType::t_弹出消息框;

	mf_布局 = on_弹出信息框布局;
	mf_绘制 = on_弹出信息框绘制;
	m_ColorA.m_颜色 = S_UI主题::uic_菜单背景;
	m_ColorA.m_模糊 = 255;


	mf_鼠标进入 = on_鼠标进入_弹出信息框;
	mf_鼠标离开 = on_鼠标移出_弹出信息框;
	f_widget_添加绘制画布(this);

	m_打开线程 = nullptr;
}

C_弹出信息框::~C_弹出信息框() {
	if (m_打开线程) {
		WaitForSingleObject(m_打开线程, INFINITE);
	}
}

C_Widget* f_ui_创建弹出消息框(S_UI渲染环境& ctx) {
	C_弹出信息框* box = new C_弹出信息框(ctx);
	return box;
}

void f_ui_弹出消息框置文本(C_Widget* self, std::vector<std::vector<std::u16string>>& text) {
	C_弹出信息框& box = *dynamic_cast<C_弹出信息框*>(self);

	box.m_text = text;
}

std::vector<std::u16string>& f_ui_取弹出消息框文本(C_Widget* self, uint32 loc) {
	C_弹出信息框& box = *dynamic_cast<C_弹出信息框*>(self);
	return box.m_text[loc];
}

uint32 f_ui_取弹出消息框文本行数量(C_Widget* self) {
	C_弹出信息框& box = *dynamic_cast<C_弹出信息框*>(self);
	return box.m_text.size();
}



